package com.mmc.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.BCrypt;
import org.springframework.data.redis.core.RedisTemplate;
import com.mmc.common.result.ResultCode;
import com.mmc.controller.AuthController;
import com.mmc.entity.User;
import com.mmc.entity.Menu;
import com.mmc.mapper.UserMapper;
import com.mmc.service.AuthService;
import com.mmc.service.MenuService;
import com.mmc.service.RoleService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import jakarta.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 认证服务实现类
 *
 * @author kunfe
 * @since 2024-01-01
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AuthServiceImpl implements AuthService {

    private final UserMapper userMapper;
    private final MenuService menuService;
    private final RoleService roleService;
    private final RedisTemplate<String, String> redisTemplate;

    @Override
    public Map<String, Object> login(AuthController.LoginRequest request) {
        // 1. 验证参数
        if (ObjectUtil.isEmpty(request.getUsername()) || ObjectUtil.isEmpty(request.getPassword())) {
            throw new RuntimeException("用户名或密码不能为空");
        }

        // 2. 验证验证码（可选，如果提供了就验证）
        if (StrUtil.isNotBlank(request.getCaptchaCode()) && StrUtil.isNotBlank(request.getCaptchaId())) {
            // 从Redis获取正确的验证码
            String correctCode = redisTemplate.opsForValue().get("captcha:" + request.getCaptchaId());
            
            if (correctCode == null) {
                throw new RuntimeException("验证码已过期");
            }
            
            // 验证码验证（不区分大小写）
            if (!correctCode.equalsIgnoreCase(request.getCaptchaCode().trim())) {
                throw new RuntimeException("验证码错误");
            }
            
            // 验证成功后删除验证码，防止重复使用
            redisTemplate.delete("captcha:" + request.getCaptchaId());
        }

        // 3. 查询用户
        User user = userMapper.selectByUsername(request.getUsername());
        if (ObjectUtil.isNull(user)) {
            throw new RuntimeException("用户不存在");
        }

        // 4. 验证密码
        if (!BCrypt.checkpw(request.getPassword(), user.getPassword())) {
            throw new RuntimeException("密码错误");
        }

        // 5. 检查用户状态
        if (user.getStatus() == 0) {
            throw new RuntimeException("用户已被禁用");
        }

        // 6. 执行登录
        StpUtil.login(user.getId());

        // 7. 更新登录信息
        user.setLastLoginTime(LocalDateTime.now());
        user.setLastLoginIp(getClientIp());
        userMapper.updateById(user);

        // 8. 构造返回结果
        Map<String, Object> result = new HashMap<>();
        result.put("token", StpUtil.getTokenValue());
        result.put("user", buildUserInfo(user));

        log.info("用户 {} 登录成功", user.getUsername());
        return result;
    }

    @Override
    public void logout() {
        Long userId = StpUtil.getLoginIdAsLong();
        StpUtil.logout();
        log.info("用户 {} 退出登录", userId);
    }

    @Override
    public User getUserInfo(Long userId) {
        User user = userMapper.selectById(userId);
        if (ObjectUtil.isNull(user)) {
            throw new RuntimeException(ResultCode.USER_NOT_FOUND.getMessage());
        }
        return buildUserInfo(user);
    }

    @Override
    public Object getUserMenus(Long userId) {
        // 根据用户权限查询菜单
        List<Menu> menus = menuService.getMenuTreeByUserId(userId);
        return menus;
    }

    @Override
    public Object getUserPermissions(Long userId) {
        // 根据用户角色查询权限
        List<String> permissions = roleService.getPermissionsByUserId(userId);
        return permissions;
    }

    @Override
    public Map<String, Object> refreshToken() {
        // 刷新Token
        StpUtil.renewTimeout(StpUtil.getLoginIdAsLong());
        
        Map<String, Object> result = new HashMap<>();
        result.put("token", StpUtil.getTokenValue());
        result.put("expire", StpUtil.getTokenTimeout());
        
        return result;
    }



    /**
     * 构建用户信息（去除敏感信息）
     */
    private User buildUserInfo(User user) {
        if (ObjectUtil.isNull(user)) {
            return null;
        }
        
        User userInfo = new User();
        userInfo.setId(user.getId());
        userInfo.setUsername(user.getUsername());
        userInfo.setRealName(user.getRealName());
        userInfo.setNickname(user.getNickname());
        userInfo.setAvatar(user.getAvatar());
        userInfo.setEmail(user.getEmail());
        userInfo.setPhone(user.getPhone());
        userInfo.setGender(user.getGender());
        userInfo.setBirthday(user.getBirthday());
        userInfo.setDeptId(user.getDeptId());
        userInfo.setPosition(user.getPosition());
        userInfo.setIntro(user.getIntro());
        userInfo.setStatus(user.getStatus());
        userInfo.setUserType(user.getUserType());
        userInfo.setLastLoginTime(user.getLastLoginTime());
        userInfo.setCreateTime(user.getCreateTime());
        
        // 设置角色和权限信息
        userInfo.setRoles(roleService.getUserRoles(user.getId()));
        userInfo.setPermissions(roleService.getPermissionsByUserId(user.getId()));
        
        return userInfo;
    }

    /**
     * 获取客户端IP地址
     */
    private String getClientIp() {
        try {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if (attributes != null) {
                HttpServletRequest request = attributes.getRequest();
                String ip = request.getHeader("X-Forwarded-For");
                if (ObjectUtil.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                    ip = request.getHeader("Proxy-Client-IP");
                }
                if (ObjectUtil.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                    ip = request.getHeader("WL-Proxy-Client-IP");
                }
                if (ObjectUtil.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                    ip = request.getHeader("HTTP_CLIENT_IP");
                }
                if (ObjectUtil.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                    ip = request.getHeader("HTTP_X_FORWARDED_FOR");
                }
                if (ObjectUtil.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                    ip = request.getRemoteAddr();
                }
                return ip;
            }
        } catch (Exception e) {
            log.warn("获取客户端IP失败", e);
        }
        return "127.0.0.1";
    }
} 